package com.avic.map.common.queue.receive;

import com.avic.map.common.constant.LocalResourceConstant;
import com.avic.map.common.constant.RabbitConstant;
import com.avic.map.common.model.GpsCarModel;
import com.avic.map.common.model.MapCommonModel;
import com.avic.map.common.model.ShipPositionModel;
import com.avic.map.common.model.ShipStatic24Model;
import com.avic.map.common.model.ShipStaticModel;
import com.avic.map.common.model.SoldierModel;
import com.avic.map.common.model.VdmShipPositionModel;
import com.avic.map.common.model.enums.MapDataStatusEnums;
import com.avic.map.common.scheduled.MapDataRecoverApplicationRunner;
import com.avic.map.dal.model.ShipStaticInfo;
import com.avic.map.dal.model.SingleSoldierResource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

/**
 * MQ 队列监控
 *
 * @author huangsheng
 */
@Component
@Slf4j
public class RabbitMqReceiver extends AbstractReceiver {

    public static ShipStaticInfo shipStaticInfo = new ShipStaticInfo();

    /**
     * 监听5号报文数据，船舶静态数据
     * 更新船舶名称
     * <p>
     */
    @RabbitHandler
    @RabbitListener(queues = RabbitConstant.SHIP_DETAIL_QUEUE_NAME)
    public void receive(String message) {
        log.info("接收到船舶5号静态详情数据 :{}", message);
        try {
            ShipStaticModel shipStaticModel = objectMapper.readValue(message, ShipStaticModel.class);
            log.info("转换出对象 shipStaticModel = {}", objectMapper.writeValueAsString(shipStaticModel));

            if (null == shipStaticModel || StringUtils.isBlank(shipStaticModel.getShipName())) {
                return;
            }
            long shipMssi = shipStaticModel.getMmsi();

            ShipStaticInfo shipStaticInfo = null;
            try {
                shipStaticInfo = shipStaticInfoService.insertShipStatic(shipStaticModel);
            } catch (Exception e) {
            }
            // 更新船舶名称
            this.receiverMessageUpdateShipName(String.valueOf(shipMssi), shipStaticInfo);
        } catch (Exception e) {
            log.warn(" receive VDM船舶静态数据时，发生错误： {}", e.getMessage());
        }
    }

    /**
     * 监听24号报文数据，船舶静态数据
     * 更新船舶名称
     * <p>
     */
    @RabbitHandler
    @RabbitListener(queues = RabbitConstant.AIS_OTHER_VESSEL_STATIC_INFO24)
    public void receiveVdm24(String message) {
        log.info("接收到vdm24报文的数据 :{}", message);
        try {
            ShipStatic24Model shipStaticModel = objectMapper.readValue(message, ShipStatic24Model.class);
            log.info("转换出对象ShipStatic24Model = {}", objectMapper.writeValueAsString(shipStaticModel));

            if (null == shipStaticModel) {
                return;
            }
            long shipMssi = shipStaticModel.getMmsi();
            ShipStaticInfo shipStaticInfo = null;
            try {
                shipStaticInfo = shipStaticInfoService.insertShipStaticByShipStatic24Model(shipStaticModel);
            } catch (Exception e) {
            }
            // 更新船舶名称
            receiverMessageUpdateShipName(String.valueOf(shipMssi), shipStaticInfo);
        } catch (Exception e) {
            log.warn(" 处理24号报文静态数据时，发生错误： {}", e.getMessage());
        }
    }

    /**
     * 监听 18、19号报文
     * VDM船舶数据
     * <p>
     */
    @RabbitHandler
    @RabbitListener(queues = {RabbitConstant.AIS_OTHER_VESSEL_STATIC_INFO18, RabbitConstant.AIS_OTHER_VESSEL_STATIC_INFO19})
    public void receiveVdmShip(String message) {
        // 判断是否恢复VDM船舶的数据
        this.recoverShipData();
        log.info("接收到VDM的船舶数据. 18、19号报文 :{}", message);
        try {
            VdmShipPositionModel vdmShipPositionModel = objectMapper.readValue(message, VdmShipPositionModel.class);
            if (null == vdmShipPositionModel) {
                return;
            }
            // 转换地图数据
            MapCommonModel newShipMapCommonModel = new MapCommonModel(vdmShipPositionModel);
            log.info("转换出VDM船舶地图对象 {}", objectMapper.writeValueAsString(newShipMapCommonModel));

            // 处理船舶数据
            vdmShipHandler(newShipMapCommonModel);
        } catch (Exception e) {
            log.warn(" 处理VDM船舶数据时发生错误： {}", e.getMessage());
        }
    }

    /**
     * 接收VDO船舶位置对象
     */
    @RabbitHandler
    @RabbitListener(queues = RabbitConstant.SHIP_POSITION_QUEUE_NAME)
    public void receiveVdoShipPosition(String message) {
        // 判断是否恢复数据
        this.recoverShipData();
        log.info("接收到VDO船舶位置消息：{}", message);
        //数据存储到redis,船的轨迹点
        try {
            ShipPositionModel shipPositionModel = objectMapper.readValue(message, ShipPositionModel.class);

            if (null != shipPositionModel) {
                String shipMssi = String.valueOf(shipPositionModel.getMmsi());
                log.info("获取到船舶mssi {}", shipMssi);

                if (!LocalResourceConstant.SHIP_STATE_DB_MAP.containsKey(shipMssi)) {
                    log.info("船舶 【{}】在基础资源里面未配置, 当做VDM的数据处理推送出去", shipMssi);
                    // 转换地图数据
                    MapCommonModel newVdmShipMapCommonModel = new MapCommonModel(
                            shipPositionModel, MapDataStatusEnums.VIDM, LocalResourceConstant.VDM_SHIP_STATE_DB_MAP.get(shipMssi));
                    // 处理船舶数据
                    vdmShipHandler(newVdmShipMapCommonModel);
                } else {
                    log.info("船舶 【{}】在基础资源里面配置，为自己的船舶数据处理", shipMssi);
                    // 转换地图数据
                    MapCommonModel newShipMapCommonModel = new MapCommonModel(
                            shipPositionModel, MapDataStatusEnums.VIDO, LocalResourceConstant.SHIP_STATE_DB_MAP.get(shipMssi));
                    log.info("转换成VDO 地图数据 {}", objectMapper.writeValueAsString(newShipMapCommonModel));

                    shipHandler(newShipMapCommonModel, shipPositionModel.getSog());
                }
            }
        } catch (Exception e) {
            log.warn("处理VDO消息时，发生错误： {}", e.getMessage());
        }
    }

    /**
     * 接收车辆的GPS信息
     * <p>
     * 接收到数据，判断是否为同一个点，或者速度为0，如果坐标或者数据正常，则记录数据，以及坐标数据
     * 更新数据库
     * 更新本地变量
     * 更新redis缓存数据
     */
    @RabbitHandler
    @RabbitListener(queues = RabbitConstant.CAR_GPS_QUEUE_NAME)
    public void receiveCar(String message) {
        // 判断是否恢复数据
        this.recoverCarData();
        log.info("接收到电台GPS详情数据 :{}", message);
        try {
            GpsCarModel gpsCarModel = objectMapper.readValue(message, GpsCarModel.class);
            if (null != gpsCarModel) {
                // 1是车辆 2是手持对讲机的单兵
                int dateType = 0;
                String gpsNumber = gpsCarModel.getTarget().getNumber();
                log.info("转换获取到GPS编号为 {}", gpsNumber);

                if (LocalResourceConstant.CAR_STATE_DB_MAP.containsKey(gpsNumber)) {
                    log.info("基础资源里配置了车辆资源【{}】", gpsNumber);
                    dateType = 1;
                }
                SingleSoldierResource singleSoldierResource = null;
                if (LocalResourceConstant.SOLDIER_STATE_DB_MAP.containsKey(gpsNumber)) {
                    log.info("基础资源里配置了单兵资源【{}】", gpsNumber);
                    singleSoldierResource = LocalResourceConstant.SOLDIER_STATE_DB_MAP.get(gpsNumber);
                    dateType = 2;
                }
                if (dateType == 0) {
                    log.info("基础资源里未配置单兵资源，也没有配置车辆资源【{}】", gpsNumber);
                    return;
                }
                // 转换地图数据
                MapCommonModel newGpsMapCommonModel = new MapCommonModel(gpsCarModel, dateType == 1 ? LocalResourceConstant.CAR_STATE_DB_MAP.get(gpsNumber) :
                        null != singleSoldierResource ? singleSoldierResource.getPersonnelCompany() : StringUtils.EMPTY);
                log.info("转换出GPS地图数据 {}", objectMapper.writeValueAsString(newGpsMapCommonModel));

                if (dateType == 1) {
                    // 该数据为车辆数据
                    carHandler(newGpsMapCommonModel);
                } else if (dateType == 2) {
                    // 该数据为单兵数据
                    int modelType = LocalResourceConstant.SOLDIER_STATE_DB_MAP.get(gpsNumber).getEquipmentType();
                    log.info("单兵编号：{}， 单兵类型 {}", gpsNumber, modelType);
                    //  该数据为单兵数据
                    soldierHandler(newGpsMapCommonModel, modelType);
                }
            }
        } catch (Exception e) {
            log.warn("处理GPS消息时，发生错误： {}", e.getMessage());
        }
    }

    private static final String SOLDIER_GPS_TYPE_MESSAGE = "9";

    /**
     * 监听单兵的数据
     * <p>
     * 存储到redis
     */
    @RabbitHandler
    @RabbitListener(queues = RabbitConstant.WS_POSITION_4G_INFO)
    public void receiveSoldier(String message) {
        // 判断是否恢复数据
        this.recoverSoldierData();
        log.info("接收到单兵数据 :{}", message);
        try {
            SoldierModel soldierModel = objectMapper.readValue(message, SoldierModel.class);
            if (null == soldierModel) {
                return;
            }
            String devId = soldierModel.getDevid();
            log.info("解析出单兵的唯一标示 {}", devId);

            if (!LocalResourceConstant.SOLDIER_STATE_DB_MAP.containsKey(devId)) {
                log.info("基础资源里未配置单兵资源【{}】", devId);
                return;
            }
            int modelType = LocalResourceConstant.SOLDIER_STATE_DB_MAP.get(devId).getEquipmentType();
            log.info("单兵编号：{}， 单兵类型 {}", devId, modelType);

            if (StringUtils.equals(soldierModel.getBstype(), SOLDIER_GPS_TYPE_MESSAGE)) {
                // 转换地图数据
                MapCommonModel newSoldierMapCommonModel = new MapCommonModel(soldierModel);
                log.info("转换出单兵地图数据 {}", newSoldierMapCommonModel);

                soldierHandler(newSoldierMapCommonModel, modelType);
            } else {
                log.info("获取到单兵数据，类型不为9，当前数据类型为 {}，不做处理", soldierModel.getBstype());
            }
        } catch (Exception e) {
            log.warn("处理单兵消息时，发生错误： {}", e.getMessage());
        }
    }


    /**
     * 恢复单兵数据
     */
    private void recoverSoldierData() {
        // 恢复数据
        if (MapDataRecoverApplicationRunner.isRecoverSoldierData) {
            MapDataRecoverApplicationRunner.isRecoverSoldierData = false;
            log.info("RabbitMqReceiver恢复船舶本地数据");
            mapDataRecoverApplicationRunner.soldierModelDataRecover();
        }
    }

    /**
     * 恢复数据
     */
    private void recoverShipData() {
        // 恢复数据
        if (MapDataRecoverApplicationRunner.isRecoverShipData) {
            MapDataRecoverApplicationRunner.isRecoverShipData = false;
            log.info("RabbitMqReceiver恢复船舶本地数据");
            mapDataRecoverApplicationRunner.mapShipDataRecover();
        }
    }


    /**
     * 恢复数据
     */
    private void recoverCarData() {
        // 恢复数据
        if (MapDataRecoverApplicationRunner.isRecoverCarData) {
            MapDataRecoverApplicationRunner.isRecoverCarData = false;
            log.info("RabbitMqReceiver恢复车辆本地数据");
            mapDataRecoverApplicationRunner.carDataRecover();
        }
    }
}
